package com.ngrok;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.Mergeable;
import org.springframework.beans.factory.InitializingBean;

import javax.annotation.processing.SupportedSourceVersion;
import javax.net.ssl.HttpsURLConnection;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.List;
/**
 * Created by pj on 2017/10/10.
 */
public class NgrokApi implements InitializingBean {

    private final static Logger loger= LoggerFactory.getLogger(NgrokApi.class);

    private transient  NgrokConfig config;
    public NgrokApi(NgrokConfig config){
        this.config=config;
    }

    @Override
    public void afterPropertiesSet()  {
        init();
    }

    public void init(){
        loger.info("NgrokApi Request.....");
        URL url=null;
        try{
            url=new URL(config.getNgrokAuthUrl());
            HttpsURLConnection httpsURLConnection= (HttpsURLConnection) url.openConnection();
            httpsURLConnection.setConnectTimeout(config.getOutTime());
            httpsURLConnection.setReadTimeout(config.getOutTime());
            httpsURLConnection.setRequestProperty("connection","Keep-Alive");
            httpsURLConnection.setRequestProperty("Host","www.ngrok.cc");
            httpsURLConnection.setRequestProperty("User-Agent","Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Mobile Safari/537.36");
            InputStream inputStream= httpsURLConnection.getInputStream();
            byte[] s=new byte[inputStream.available()];
            inputStream.read(s);
            inputStream.close();
            API api=JSON.parseObject(s,API.class);
            API apitarger=this.config.getApi();
            if(apitarger!=null){
                merge(apitarger.getData().get(0),api.getData().get(0));
                api.setData(apitarger.getData());
            }
            this.config.setApi(api);
            loger.info("NgrokApi Response.....             "+api.getServer()+":"+api.getProt());
        } catch (MalformedURLException e) {
            loger.error(e.getMessage());
        } catch (SocketTimeoutException e) {
            loger.error(url+e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public  <M> void merge(M target, M destination) throws Exception {
        BeanInfo beanInfo = Introspector.getBeanInfo(target.getClass());
        for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) {
            System.out.println(descriptor.toString());
            if (descriptor.getWriteMethod() != null) {
                Object originalValue = descriptor.getReadMethod()
                        .invoke(target);
                if (originalValue == null) {
                    Object defaultValue = descriptor.getReadMethod().invoke(
                            destination);
                    descriptor.getWriteMethod().invoke(target, defaultValue);
                }

            }
        }
    }
    public NgrokConfig getConfig() {
        return config;
    }

    public void setConfig(NgrokConfig config) {
        this.config = config;
    }

   public static class API{
        private String msg;
        private String server;
        private int prot;
        private List<Data> data;
        private String status;

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public String getServer() {
            return server;
        }

        public void setServer(String server) {
            if (server!=null){
                int index=server.indexOf(":");
                if(index!=-1){
                    prot=Integer.valueOf(server.substring(index+1,server.length()));
                    server=server.substring(0,index);
                }
            }
            this.server = server;
        }

        public List<Data> getData() {
            return data;
        }

        public void setData(List<Data> data) {
            this.data = data;
        }

        public String getStatus() {
            return status;
        }

        public void setStatus(String status) {
            this.status = status;
        }

       public int getProt() {
           return prot;
       }

       public void setProt(int prot) {
           this.prot = prot;
       }
   }
    public static  class Data{
        private String hostname;
        private String httpauth;
        private  Proto proto;
        private String  subdomain;
        private String remoteport;

        public String getHostname() {
            return hostname;
        }

        public void setHostname(String hostname) {
            this.hostname = hostname;
        }

        public String getHttpauth() {
            return httpauth;
        }

        public void setHttpauth(String httpauth) {
            this.httpauth = httpauth;
        }

        public Proto getProto() {
            return proto;
        }

        public void setProto(Proto proto) {
            this.proto = proto;
        }

        public String getSubdomain() {
            return subdomain;
        }

        public void setSubdomain(String subdomain) {
            this.subdomain = subdomain;
        }

        public String getRemoteport() {
            return remoteport;
        }

        public void setRemoteport(String remoteport) {
            this.remoteport = remoteport;
        }
    }
    public  static   class  Proto{
        private String http;

        private int prot;

        public String getHttp() {
            return http;
        }

        public int getProt() {
            return prot;
        }

        public void setProt(int prot) {
            this.prot = prot;
        }

        public void setHttp(String http) {
            if(http!=null){
                int index=http.indexOf(":");
                if(index!=-1){
                    prot=Integer.valueOf(http.substring(index+1,http.length()));
                    http=http.substring(0,index);
                }
            }
            this.http = http;
        }
    }
}
